import 'dart:async';
import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:flutter_rtk/api/api.dart';
import 'package:flutter_rtk/common/assets.dart';
import 'package:flutter_rtk/common/common.dart';
import 'package:flutter_rtk/common/constants.dart';
import 'package:flutter_rtk/entities/login_entity.dart';
import 'package:flutter_rtk/models/app_model.dart';
import 'package:flutter_rtk/models/login_model.dart';
import 'package:flutter_rtk/models/user_info_model.dart';
import 'package:flutter_rtk/router/index.dart';
import 'package:flutter_rtk/service/connectivity_service.dart';
import 'package:flutter_rtk/service/database_service.dart';
import 'package:flutter_rtk/service/store_service.dart';
import 'package:flutter_rtk/utils/md5_utils.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:provider/provider.dart';

// ignore: must_be_immutable
class LoginPage extends StatefulWidget {
  const LoginPage({super.key});

  @override
  State<LoginPage> createState() => _LoginPageState();
}

class _LoginPageState extends State<LoginPage> {
  bool canLogin = false;
  bool pwdShow = false;
  String username = "";
  String password = "";

  late TextEditingController _usernameController;
  late TextEditingController _passwordController;
  late TextEditingController _newHostController;
  late FocusNode _usernameFocusNode;

  // scan code
  late String scene;

  Timer? timer;

  // switch
  bool isPasswordLogin = true;

  @override
  void initState() {
    super.initState();
    _usernameController = TextEditingController();
    _passwordController = TextEditingController();
    _newHostController = TextEditingController();
    _usernameFocusNode = FocusNode();
  }

  @override
  void dispose() {
    _usernameController.dispose();
    _passwordController.dispose();
    _newHostController.dispose();
    _usernameFocusNode.dispose();
    timer?.cancel();
    super.dispose();
  }

  Widget _buildMainView() {
    Size size = MediaQuery.of(context).size;
    return Scaffold(
      resizeToAvoidBottomInset: false,
      body: Stack(children: [
        buildLoginBg(size: size),
        SingleChildScrollView(
          physics: const NeverScrollableScrollPhysics(),
          child: Center(
            child: Container(
              width: 650.w,
              height: 860.h,
              margin: EdgeInsets.only(top: (size.height - 860.h) / 2),
              decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(30.r)),
              child: Column(crossAxisAlignment: CrossAxisAlignment.center, children: [
                SizedBox(height: 200.h),
                buildSwitchLoginWay(),
                isPasswordLogin ? SizedBox(height: 80.h) : const SizedBox.shrink(),
                isPasswordLogin ? buildAccountInput() : const SizedBox.shrink(),
                isPasswordLogin ? SizedBox(height: 30.h) : const SizedBox.shrink(),
                isPasswordLogin ? buildPasswordInput() : const SizedBox.shrink(),
                isPasswordLogin ? SizedBox(height: 60.h) : const SizedBox.shrink(),
                isPasswordLogin ? buildLoginBtn() : const SizedBox.shrink(),
                isPasswordLogin ? const SizedBox.shrink() : buildScanLoginView(),
              ]),
            ),
          ),
        ),
        // logo
        buildLoginLogo(size: size),
      ]),
    );
  }

  Positioned buildLoginLogo({required Size size, double containerHeight = 860}) {
    return Positioned(
      top: (size.height - containerHeight.h - 295.h) / 2,
      left: (size.width - 247.w) / 2,
      child: Container(width: 247.w, height: 295.h, alignment: Alignment.center, decoration: const BoxDecoration(image: DecorationImage(image: AssetImage(AppAssets.loginLogoBg))), child: Image.asset(AppAssets.loginLogo, width: 160.w, height: 160.h)),
    );
  }

  SizedBox buildLoginBg({required Size size}) {
    return SizedBox(width: size.width, height: size.height, child: Image.asset(AppAssets.loginBg, fit: BoxFit.cover));
  }

  buildScanLoginView() {
    return Container(
      width: double.infinity,
      height: 584.h,
      decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(8.r)),
      child: Column(crossAxisAlignment: CrossAxisAlignment.center, children: [
        SizedBox(height: 44.h),
        Consumer<LoginModel>(builder: (context, login, child) {
          if (login.isLoadScanCode == -1) {
            return Container(width: 400.w, height: 400.w, decoration: BoxDecoration(border: Border.all(color: const Color(0xFFD8D8D8))), child: const Text("二维码获取失败"));
          } else if (login.isLoadScanCode == 1) {
            return Container(width: 400.w, height: 400.w, decoration: BoxDecoration(border: Border.all(color: const Color(0xFFD8D8D8))), child: Center(child: SizedBox(width: 40.w, height: 40.w, child: const CircularProgressIndicator())));
          }
          // 状态：1、未鉴权，2、已授权，3、已登录，4、已失效
          return Stack(children: [
            Container(width: 400.w, height: 400.w, decoration: BoxDecoration(border: Border.all(color: const Color(0xFFD8D8D8), width: 1.w)), child: login.qrCodeImage),
            login.codeStatus == 2 || login.codeStatus == 4
                ? Container(
                    width: 400.w,
                    height: 400.w,
                    decoration: BoxDecoration(border: Border.all(color: const Color(0xFFD8D8D8)), color: Colors.black.withAlpha(150)),
                    child: Center(
                      child: Container(
                        width: 300.w,
                        height: 80.h,
                        padding: EdgeInsets.symmetric(horizontal: 20.w),
                        decoration: BoxDecoration(borderRadius: BorderRadius.circular(12.r), color: Colors.white),
                        child: FittedBox(child: login.codeStatus == 2 ? const Text("已授权") : const Text("二维码已失效")),
                      ),
                    ),
                  )
                : const SizedBox.shrink(),
          ]);
        }),
        SizedBox(height: 10.h),
        InkWell(
          onTap: () {
            context.read<LoginModel>().changeLoadStatus(1);
            // fetch api
            scene = MD5Utils.toMD5(DateTime.now().millisecondsSinceEpoch.toString()).substring(0, 16);
            _fetchCode(scene: scene);
            startNewTimer();
          },
          child: FittedBox(
            child: Row(children: [
              SizedBox(width: 28.w, height: 28.w, child: Image.asset(AppAssets.refreshIcon)),
              SizedBox(width: 18.w),
              Text("刷新二维码", style: TextStyle(fontSize: 28.sp, color: const Color(0xFF999999), fontWeight: FontWeight.w500)),
            ]),
          ),
        ),
        SizedBox(height: 10.h),
        Text("请使用微信扫码登录", style: TextStyle(fontSize: 30.sp, color: const Color(0xFF999999), fontWeight: FontWeight.w500)),
      ]),
    );
  }

  Container buildLoginBtn() {
    return Container(
      margin: EdgeInsets.symmetric(horizontal: 70.w),
      width: double.infinity,
      height: 80.h,
      child: TextButton(
        style: ButtonStyle(
          splashFactory: NoSplash.splashFactory,
          backgroundColor: MaterialStateProperty.all(
            canLogin ? AppConstants.brandColor : const Color(0xFF6FA6FC),
          ),
          shape: MaterialStateProperty.all(
            RoundedRectangleBorder(borderRadius: BorderRadius.circular(90.r)),
          ),
          padding: MaterialStateProperty.all(EdgeInsets.zero),
          elevation: MaterialStateProperty.all(0),
        ),
        onPressed: () async {
          if (!canLogin) {
            return;
          }
          if (ConnectivityService.to.isOnline) {
            try {
              LoginEntity loginEntity = await AppApi.login(username: _usernameController.value.text.trim(), password: _passwordController.value.text.trim());
              if (loginEntity.error != null) {
                debugPrint(jsonEncode(loginEntity.toJson()));
                showToast(loginEntity.errorDescription ?? "登陆失败");
                _usernameController.text = "";
                _passwordController.text = "";
                setState(() {
                  canLogin = false;
                });
                _usernameFocusNode.requestFocus();
                return;
              }
              // 写入用户
              await DatabaseService.to.insert(tableName: "t_user", data: {
                "id": 1,
                "username": _usernameController.value.text.trim(),
                "password": MD5Utils.toMD5(_passwordController.value.text.trim()),
                "login_info": jsonEncode(loginEntity.toJson()),
              });

              _loginSuccess(loginEntity);
            } on Exception catch (e, stack) {
              debugPrintStack(stackTrace: stack);
              showToast("登陆失败: 服务异常, 请稍后再试");
              _usernameController.text = "";
              _passwordController.text = "";
              setState(() {
                canLogin = false;
              });
              _usernameFocusNode.requestFocus();
              return;
            }
          } else {
            // 离线登陆
            List<Map<String, Object?>> users = await DatabaseService.to.find(tableName: "t_user", where: "id = ?", whereArgs: [1]);
            if (users.isEmpty) {
              showToast("查无用户");
              return;
            }
            Map<String, dynamic> user = users[0];
            if (_usernameController.value.text.trim() == user['username'] && MD5Utils.toMD5(_passwordController.value.text.trim()) == user['password']) {
              _loginSuccess(LoginEntity.fromJson(jsonDecode(user['login_info'])));
            } else {
              showToast("账号或密码错误");
            }
          }
        },
        child: Text("登 录", style: TextStyle(fontSize: 30.sp, color: Colors.white, fontWeight: FontWeight.w600)),
      ),
    );
  }

  buildSwitchLoginWay() {
    return SizedBox(
      width: double.infinity,
      height: 45.h,
      child: Row(mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [
        const Spacer(),
        InkWell(
          onTap: () {
            // 取消二维码定时检测
            timer?.cancel();
            setState(() {
              isPasswordLogin = true;
            });
          },
          child: Text("密码登录", style: isPasswordLogin ? TextStyle(fontSize: 34.sp, color: const Color(0xFF007AFF)) : TextStyle(fontSize: 24.sp, color: const Color(0xFF666666))),
        ),
        SizedBox(width: 55.w),
        InkWell(
          onTap: () {
            if (!ConnectivityService.to.isOnline) {
              showToast("离线状态不允许扫码登陆");
              return;
            }
            setState(() {
              context.read<LoginModel>().changeLoadStatus(1);
              context.read<LoginModel>().changeCodeStatus(1);
              isPasswordLogin = false;
              // 获取二维码
              scene = MD5Utils.toMD5(DateTime.now().millisecondsSinceEpoch.toString()).substring(0, 16);
              _fetchCode(scene: scene);
              // 检测状态
              startNewTimer();
            });
          },
          child: Text("扫码登录", style: !isPasswordLogin ? TextStyle(fontSize: 34.sp, color: const Color(0xFF007AFF)) : TextStyle(fontSize: 24.sp, color: const Color(0xFF666666))),
        ),
        const Spacer(),
      ]),
    );
  }

  Container buildAccountInput() {
    return Container(
      margin: EdgeInsets.symmetric(horizontal: 70.w),
      child: TextField(
        controller: _usernameController,
        focusNode: _usernameFocusNode,
        decoration: InputDecoration(
          hintText: "请输入账号",
          hintStyle: TextStyle(
            fontSize: 36.sp,
            color: const Color(0xFFD1D1D1),
            fontWeight: FontWeight.w500,
          ),
          enabledBorder: const UnderlineInputBorder(borderSide: BorderSide(color: Color(0xFFE7E7E7))),
        ),
        textInputAction: TextInputAction.next,
        onChanged: (v) {
          username = v;
          if (username.isNotEmpty && password.isNotEmpty) {
            setState(() {
              canLogin = true;
            });
          }
        },
      ),
    );
  }

  Container buildPasswordInput() {
    return Container(
      margin: EdgeInsets.symmetric(horizontal: 70.w),
      child: TextField(
        controller: _passwordController,
        obscureText: !pwdShow,
        decoration: InputDecoration(
          hintText: "请输入密码",
          hintStyle: TextStyle(
            fontSize: 36.sp,
            color: const Color(0xFFD1D1D1),
            fontWeight: FontWeight.w500,
          ),
          enabledBorder: const UnderlineInputBorder(borderSide: BorderSide(color: Color(0xFFE7E7E7))),
          // suffixIcon: IconButton(
          //   icon: pwdShow ? const Icon(Icons.visibility) : const Icon(Icons.visibility_off, color: Color(0xFFE7E7E7)),
          //   onPressed: () {
          //     setState(() {
          //       pwdShow = !pwdShow;
          //     });
          //   },
          // ),
        ),
        contextMenuBuilder: (context, editableTextState) => Container(),
        onChanged: (v) async {
          password = v;
          if (username.isNotEmpty && password.isNotEmpty) {
            setState(() {
              canLogin = true;
            });
          }
        },
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return _buildMainView();
  }

  _fetchCode({required String scene}) {
    AppApi.scanLogin(scene: scene).then((value) {
      context.read<LoginModel>().changeLoadStatus(0);
      context.read<LoginModel>().setImage(Image.memory(base64Decode(value)));
    }).onError((error, stackTrace) {
      context.read<LoginModel>().changeLoadStatus(-1);
    });
  }

  void startNewTimer() {
    timer?.cancel();
    context.read<LoginModel>().changeCodeStatus(1);
    timer = Timer.periodic(const Duration(seconds: 3), (timer) {
      try {
        _fetchCodeStatus(scene: scene);
      } catch (e, stack) {
        debugPrintStack(stackTrace: stack);
      }
    });
  }

  _fetchCodeStatus({required String scene}) {
    AppApi.scanStatus(scene: scene).then((data) {
      int code = data['status'] ?? 1;
      context.read<LoginModel>().changeCodeStatus(code);
      // 状态：1、未鉴权，2、已授权，3、已登录，4、已失效
      if (code == 3) {
        timer?.cancel();
        var loginEntity = LoginEntity.fromJson(data['data']);
        _loginSuccess(loginEntity);
      }
      if (code == 4) {
        timer?.cancel();
      }
    }).onError((error, stackTrace) {
      debugPrintStack(stackTrace: stackTrace);
    });
  }

  _loginSuccess(LoginEntity loginEntity) async {
    // store token
    await StoreService.to.setString(AppConstants.token, "bearer ${loginEntity.accessToken}");
    // store token expire time
    await StoreService.to.setInt(AppConstants.tokenExpireTime, (loginEntity.expiresIn ?? 120) * 1000 + DateTime.now().millisecond);
    // await StoreService.to.setString(AppConstants.loginInfo, jsonEncode(res));
    // if (isAutoLogin) {
    //   await StoreService.to.setString(AppConstants.loginUserName, username);
    //   await StoreService.to.setString(AppConstants.loginPassword, password);
    //   await StoreService.to.setInt(AppConstants.autoLoginTime, DateTime.now().millisecondsSinceEpoch);
    // }
    // await StoreService.to.setBool(AppConstants.autoLogin, isAutoLogin);
    await StoreService.to.setBool(AppConstants.userIsLogin, true);
    context.read<UserInfoModel>().loginSuccess(loginEntity);
    context.read<AppModel>().resetCurrentIdx();
    showToast("登陆成功");
    Navigator.of(context).pushNamedAndRemoveUntil(AppRouters.initial, (router) => false);
  }
}
